﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security;
using System.Collections.Concurrent;
using System.Collections;
using System.Drawing;
using System.Dynamic;

using System.Threading;
using System.Net;
using Newtonsoft.Json;
using System.Diagnostics;
using System.Windows.Forms;
using System.Windows.Media.Imaging; //
using App2Wpf.Models;
using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using System.ComponentModel;
using System.Windows.Threading;
using App2Wpf.Views;


namespace App2Wpf
{
    public class ViewerRender : ViewerBase
    {
        
        DrawingVisual _drawingVisual;

        
        //public bool IsShowControlWindow;

        public ViewerRender(IPAddress Server, nameip wininfo) : base(Server, wininfo)
        {
            
        }

        override public void init(IPAddress server)
        {

            //Session successfully established, start streaming...

            //Create WinForms Environment...
            VirtualDeskForm = new CardModel();
            

            //(VirtualDeskForm.pictureBox1 as Control).MouseDown += logic_MouseDown;
            //(VirtualDeskForm.pictureBox1 as Control).MouseUp += logic_MouseUp;
            //(VirtualDeskForm.pictureBox1 as Control).MouseMove += logic_MouseMove;
            //(VirtualDeskForm.pictureBox1 as Control).MouseWheel += logic_MouseWheel;

            //(VirtualDeskForm.pictureBox1 as Control).DoubleClick += logic_DoubleClick;
            //(VirtualDeskForm.pictureBox1 as Control).KeyPress += logic_KeyPress;
            //(VirtualDeskForm.pictureBox1 as Control).KeyUp += logic_KeyUp;
            //(VirtualDeskForm.pictureBox1 as Control).KeyDown += logic_KeyDown;
            //(VirtualDeskForm.pictureBox1 as Control).Leave += logic_Leave;

            //this.virtualDesktopDic = new Dictionary<int, remoteWindow>();
            //virtualDesktopDic.Add(0, VirtualDeskForm);

            var tempHashtable = new Hashtable();
            tempHashtable.Add("VirtualDesktop", VirtualDeskForm);
            var virtualDesktopSyncHash = Hashtable.Synchronized(tempHashtable);

            VirtualDeskForm.cardTitle = string.Format(
                "{0} {1}[{2}x{3}]:{4}/{5}-{6}",
                wininfo.name,
                wininfo.ip,
                0,
                0,
                //session.ServerInformation.Version,
                0,
                0,
                0);
            //加载窗口后刷新 20230520
            //Session successfully established, start streaming...
            this.session = new clientViewerSession();
            this.session.Server = server;
            //Task.Run(() =>
            //{
                session.OpenSession();
                session.ConnectDesktopWorker();
                session.ConnectEventsWorker();
                //OnConnect();
                var outputEvent = new Hashtable();
                outputEvent.Add("Writer", session.ClientEvents.Writer);
                outputEventSyncHash = Hashtable.Synchronized(outputEvent);
                outputEventSyncDic.GetOrAdd("outputEvent", session.ClientEvents);

                VirtualDeskForm.cardTitle = string.Format(
                    "{0} {1}[{2}x{3}]:{4}/{5}-{6}",
                    wininfo.name,
                    wininfo.ip,
                    session.ViewerConfiguration.RemoteDesktopWidth,
                    session.ViewerConfiguration.RemoteDesktopHeight,
                    //session.ServerInformation.Version,
                    session.ServerInformation.Username,
                    session.ServerInformation.MachineName,
                    session.ServerInformation.WindowsVersion);

                //test 20221107
                //VirtualDeskForm.ClientSize = new Size(
                //    session.ViewerConfiguration.VirtualDesktopWidth,
                //    session.ViewerConfiguration.VirtualDesktopHeight);

                //  Create a thread-safe hashtable to send events to remote server.

                //Hashtable outputable = new Hashtable();
                //outputable.Add("Writer", session.ClientEvents.Writer);
                //var outputEventSyncHash = Hashtable.Synchronized(outputable);

                if (!session.ServerInformation.ViewOnly)
                {

                }

                VirtualDesktopUpdater(session.ClientDesktop,
                virtualDesktopSyncHash,
                session.ViewerConfiguration,
                session.PacketSize);

            //});


            IngressEventUpdater(session.ClientEvents, virtualDesktopSyncHash, Clipboard);


            //EgressEventUpdater(virtualDesktopSyncHash, Clipboard);
        }


        override public void VirtualDesktopUpdater(ClientIO Client,
                Hashtable virtualDesktopSyncHash,
                clientViewerConfiguration ViewerConfiguration,
                PacketSize packetSize)
        {
            byte[] mstruct = new byte[sizeof(Int32) * 3];
            System.IO.MemoryStream mstream = new System.IO.MemoryStream();

            // //bitmap direct operation
            //Bitmap scene = new Bitmap(ViewerConfiguration.RemoteDesktopWidth, ViewerConfiguration.RemoteDesktopHeight);
            //Graphics sceneGraphics = Graphics.FromImage(scene);
            //sceneGraphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;

            //while (!virtualDesktopDic[0].Form.Visible)
            //{
            //    Thread.Sleep(100);

            //}

            //Tiny hack to correctly bring to front window, this is the most effective technique so far.
            //VirtualDesktopSyncHash.VirtualDesktop.Form.TopMost = true;
            //VirtualDesktopSyncHash.VirtualDesktop.Form.TopMost = false;

            Task.Run(() =>
            {

                //// UI线程上提前创建依赖对象
                App.Current.Dispatcher.Invoke(() => {

                    ////画布
                    m_bitmapSource = new RenderTargetBitmap(
                    ViewerConfiguration.RemoteDesktopWidth,
                    ViewerConfiguration.RemoteDesktopHeight,
                    96,
                    96,
                    PixelFormats.Pbgra32);

                    // 创建一个DrawingVisual对象
                    _drawingVisual = new DrawingVisual();
                });
                

                Point destPoint = new Point(0, 0);

                while (true)
                {
                    if (IsStop) return;
                    try
                    {
                        Client.SSLStream.Read(mstruct, 0, mstruct.Length);
                        long totalBufferSize = System.Runtime.InteropServices.Marshal.ReadInt32(mstruct, 0x0);
                        destPoint.X = System.Runtime.InteropServices.Marshal.ReadInt32(mstruct, 0x4);
                        destPoint.Y = System.Runtime.InteropServices.Marshal.ReadInt32(mstruct, 0x8);
                        mstream.SetLength(totalBufferSize);

                        mstream.Position = 0;

                        while (mstream.Position != mstream.Length)
                        {
                            long bufferSize = mstream.Length - mstream.Position;
                            if (bufferSize > (long)packetSize)
                            {
                                bufferSize = (long)packetSize;
                                int mbufferSize = (int)packetSize;

                            }
                            //读数据数据流到内存中
                            mstream.Write(  Client.BinaryReader.ReadBytes((int)bufferSize),
                                0, 
                                (int)bufferSize );
                        }
                        if (mstream.Length == 0)
                        {
                            continue;
                        }

                        ///# Next Iterations
                        //sceneGraphics.DrawImage(
                        //        System.Drawing.Image.FromStream(mstream),
                        //        destPoint
                        //    );

                        //mstream.Seek(0, System.IO.SeekOrigin.Begin); //指向开始图像头
                        mstream.Position = 0;
                        App.Current.Dispatcher.Invoke(() =>
                        {
                            BitmapSource bitmapSource = clientFunc.msToBitmapImage(mstream);
                            //// 将Bitmap对象转换为BitmapSource对象
                            //BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                            //frame.GetHbitmap(),
                            //IntPtr.Zero,
                            //System.Windows.Int32Rect.Empty,
                            //BitmapSizeOptions.FromEmptyOptions());

                            // 在DrawingVisual中绘制图像
                            using (DrawingContext drawingContext = _drawingVisual.RenderOpen())
                            {
                                drawingContext.DrawImage(bitmapSource, new System.Windows.Rect(destPoint.X, destPoint.Y, bitmapSource.PixelWidth, bitmapSource.PixelHeight));
                            }
                            (m_bitmapSource as RenderTargetBitmap).Render(_drawingVisual);

                            /*
                             * 以下冗余由跨线程访问产生
                             * 
                            //System.ArgumentException: 无法冻结传递给 ImageVisualManager 的 Image 
                            //System.InvalidOperationException: 调用线程无法访问此对象，因为另一个线程拥有该对象。
                            //以下 冻结克隆副本给 UI 线程访问
                            //RenderTargetBitmap temp = (RenderTargetBitmap)renderTargetBitmap.Clone();
                            //temp.Freeze();
                            //if (temp != null)
                            //{
                            //    App.Current.Dispatcher.Invoke(() => m_bitmapSource = temp);
                            //}
                            //temp = null;*/
                            if (null != m_bitmapSource
                            && IsShowControlWindow
                            && remoteWin != null ) remoteWin._remoteImage.Source = m_bitmapSource;
                            bitmapSource = null;

                            
                        });
                        //VirtualDeskForm.cardFrame = clientFunc.BytesToBitmapImage(mstream);
                        //VirtualDeskForm.cardFrame = (BitmapImage)sourceConverter.ConvertFrom(scene);
                        //VirtualDeskForm.cardFrame = clientFunc.BitmapToBitmapImage(scene);
                        //Trace.WriteLine($"X:{destPoint.X}，Y:{destPoint.Y}，");
                        //Trace.Flush();
                        
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine(DateTime.Now);
                        Trace.WriteLine($"{destPoint.X}，{destPoint.Y},");
                        Trace.WriteLine(e);
                        Trace.Flush();
                        Trace.Close();
                        clientFunc.ShowErrorlog(e.Message);
                        break;
                        //throw;
                    }

                    //finally
                    //{
                    //    if (scene != null)
                    //    {
                    //        scene.Dispose();
                    //    }

                    //    if (sceneGraphics != null)
                    //    {
                    //        sceneGraphics.Dispose();
                    //    }

                    //    if (mstream != null)
                    //    {
                    //        mstream.Close();
                    //    }
                    //}
                }
            }


              //VirtualDesktopSyncHash.VirtualDesktop.Close();
              
              );
            //DesktopUpdater.Start();



        }


        public void initShowBigWindow()
        {
            if (null == remoteWin)
            {
                remoteWin = new WPFWindow();
                remoteWin.theOnClosing += () => this.IsShowControlWindow = false;
                remoteWin.view = this;
                ////remoteWin._remoteImage  //不限制内部可以缩放 缩放需要计算比例 保证鼠标坐标
                //remoteWin._remoteImage.Width = session.ViewerConfiguration.VirtualDesktopWidth;
                //remoteWin._remoteImage.Height = session.ViewerConfiguration.VirtualDesktopHeight;

                remoteWin.Width = session.ViewerConfiguration.VirtualDesktopWidth;
                remoteWin.Height = session.ViewerConfiguration.VirtualDesktopHeight +30;
                ////标题
                remoteWin.Title = VirtualDeskForm.cardTitle;
                remoteWin.myTitle.Text = VirtualDeskForm.cardTitle;
            }
            if (remoteWin.Visibility != System.Windows.Visibility.Visible)
                remoteWin.Visibility = System.Windows.Visibility.Visible;

            ////直接传递整个图片
            remoteWin._remoteImage.Source = m_bitmapSource;
            
        }

    }
}
